package com.dxjd.multi_camera_plugin

import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.os.Environment
import android.util.Log
import android.util.Size
import android.view.Surface
import androidx.annotation.OptIn
import androidx.camera.core.CameraSelector
import androidx.camera.core.ExperimentalGetImage
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageProxy
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleOwner
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result as FlutterResult
import io.flutter.view.TextureRegistry
import kotlinx.coroutines.*
import java.io.File

/** MultiCameraPlugin */
@OptIn(ExperimentalGetImage::class)
class MultiCameraPlugin : FlutterPlugin, MethodCallHandler, ActivityAware, MultiCameraHostApi {
    private val TAG = "MultiCameraPlugin"
    private var flutterPluginBinding: FlutterPlugin.FlutterPluginBinding? = null
    private var activity: Activity? = null
    private var context: Context? = null
    private var nativeCameraManager: NativeCameraManager? = null
    private var flutterApi: MultiCameraFlutterApi? = null
    private val coroutineScope = CoroutineScope(Dispatchers.Main + SupervisorJob())

    // 用于管理相机预览纹理
    private var textureEntry: TextureRegistry.SurfaceTextureEntry? = null

    companion object {
        private var currentInstance: MultiCameraPlugin? = null

        fun getCurrentCameraManager(): NativeCameraManager? {
            return currentInstance?.nativeCameraManager
        }
    }

    override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        Log.d(TAG, "onAttachedToEngine")
        this.flutterPluginBinding = binding
        this.context = binding.applicationContext
        MultiCameraHostApi.setUp(binding.binaryMessenger, this)
        flutterApi = MultiCameraFlutterApi(binding.binaryMessenger)
    }

    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        Log.d(TAG, "onDetachedFromEngine")
        MultiCameraHostApi.setUp(binding.binaryMessenger, null)
        disposeCameraResources()
        coroutineScope.cancel()
        this.flutterPluginBinding = null
        this.context = null
    }

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        Log.d(TAG, "onAttachedToActivity")
        activity = binding.activity
        if (context == null) {
            context = binding.activity.applicationContext
        }
    }

    override fun onDetachedFromActivity() {
        Log.d(TAG, "onDetachedFromActivity")
        activity = null
    }

    override fun onDetachedFromActivityForConfigChanges() {
        onDetachedFromActivity()
    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
        onAttachedToActivity(binding)
    }

    override fun onMethodCall(call: MethodCall, result: FlutterResult) {
        when (call.method) {
            "getPlatformVersion" -> {
                result.success("Android ${android.os.Build.VERSION.RELEASE}")
            }
            else -> {
                result.notImplemented()
            }
        }
    }

    private fun getNativeCameraManager(): NativeCameraManager {
        if (nativeCameraManager == null) {
            val activity = this.activity ?: throw IllegalStateException("Activity not available")
            val lifecycleOwner = activity as? LifecycleOwner
                ?: throw IllegalStateException("Activity must be a LifecycleOwner")
            nativeCameraManager = NativeCameraManager(activity.applicationContext, lifecycleOwner)
        }
        return nativeCameraManager!!
    }

    // ========== Pigeon API 实现 ==========

    override fun getCameraCapabilities(callback: (Result<CameraCapabilities>) -> Unit) {
        coroutineScope.launch {
            try {
                val context = this@MultiCameraPlugin.context ?: run {
                    callback(Result.failure(MultiCameraFlutterError("NO_CONTEXT", "Context not available", null)))
                    return@launch
                }

                val manager = getNativeCameraManager()
                val capabilities = CameraCapabilities(
                    supportedImplementations = listOf(CameraImplementationType.NATIVE),
                    hasFrontCamera = manager.hasFrontCamera(),
                    hasBackCamera = manager.hasBackCamera(),
                    hasFlash = manager.hasFlash(),
                    hasZoom = false // 暂不支持变焦
                )
                callback(Result.success(capabilities))
            } catch (e: Exception) {
                callback(Result.failure(MultiCameraFlutterError("GET_CAPABILITIES_FAILED", e.message ?: "Unknown error", null)))
            }
        }
    }

    override fun initializeCamera(
        config: CameraConfig,
        implementationType: CameraImplementationType,
        callback: (Result<Unit>) -> Unit
    ) {
        coroutineScope.launch {
            try {
                val manager = getNativeCameraManager()
                val lensFacing = when (config.lensDirection) {
                    CameraLensDirection.FRONT -> CameraSelector.LENS_FACING_FRONT
                    CameraLensDirection.BACK -> CameraSelector.LENS_FACING_BACK
                    else -> CameraSelector.LENS_FACING_BACK
                }

                manager.initialize(lensFacing, object : NativeCameraManager.CameraCallback {
                    override fun onInitialized() {
                        flutterApi?.onCameraStatusChanged(CameraStatus.INITIALIZED) {}
                        callback(Result.success(Unit))
                    }

                    override fun onError(error: String) {
                        val cameraError = CameraError("INITIALIZATION_FAILED", error, null)
                        flutterApi?.onCameraError(cameraError) {}
                        callback(Result.failure(MultiCameraFlutterError("INITIALIZATION_FAILED", error, null)))
                    }

                    override fun onPhotoTaken(imagePath: String, fileSize: Long) {
                        // 处理拍照完成
                    }
                })
            } catch (e: Exception) {
                callback(Result.failure(MultiCameraFlutterError("INITIALIZATION_FAILED", e.message ?: "Unknown error", null)))
            }
        }
    }

    override fun switchImplementation(
        implementationType: CameraImplementationType,
        callback: (Result<Unit>) -> Unit
    ) {
        // 原生实现只支持一种类型，直接返回成功
        callback(Result.success(Unit))
    }

    override fun switchCamera(
        direction: CameraLensDirection,
        callback: (Result<Unit>) -> Unit
    ) {
        coroutineScope.launch {
            try {
                val manager = getNativeCameraManager()
                val targetLensFacing = when (direction) {
                    CameraLensDirection.FRONT -> CameraSelector.LENS_FACING_FRONT
                    CameraLensDirection.BACK -> CameraSelector.LENS_FACING_BACK
                    CameraLensDirection.EXTERNAL -> CameraSelector.LENS_FACING_BACK // 外置摄像头退化为后置
                }
                manager.switchCamera(targetLensFacing)
                callback(Result.success(Unit))
            } catch (e: Exception) {
                callback(Result.failure(MultiCameraFlutterError("SWITCH_CAMERA_FAILED", e.message ?: "Unknown error", null)))
            }
        }
    }

    override fun takePicture(callback: (Result<CaptureResult>) -> Unit) {
        coroutineScope.launch {
            try {
                val context = this@MultiCameraPlugin.context ?: run {
                    callback(Result.failure(MultiCameraFlutterError("NO_CONTEXT", "Context not available", null)))
                    return@launch
                }

                val manager = getNativeCameraManager()
                val outputDir = File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "multi_camera")
                if (!outputDir.exists()) {
                    outputDir.mkdirs()
                }

                // 设置拍照回调
                manager.setCallback(object : NativeCameraManager.CameraCallback {
                    override fun onInitialized() {}
                    override fun onError(error: String) {
                        callback(Result.failure(MultiCameraFlutterError("CAPTURE_FAILED", error, null)))
                    }
                    override fun onPhotoTaken(imagePath: String, fileSize: Long) {
                        val result = CaptureResult(
                            imagePath = imagePath,
                            timestamp = System.currentTimeMillis(),
                            fileSize = fileSize
                        )
                        callback(Result.success(result))
                    }
                })

                manager.takePicture(outputDir)
            } catch (e: Exception) {
                callback(Result.failure(MultiCameraFlutterError("CAPTURE_FAILED", e.message ?: "Unknown error", null)))
            }
        }
    }

    override fun setFlashMode(mode: FlashMode, callback: (Result<Unit>) -> Unit) {
        try {
            val manager = getNativeCameraManager()
            val flashMode = when (mode) {
                FlashMode.OFF -> ImageCapture.FLASH_MODE_OFF
                FlashMode.ON -> ImageCapture.FLASH_MODE_ON
                FlashMode.AUTO -> ImageCapture.FLASH_MODE_AUTO
                FlashMode.TORCH -> ImageCapture.FLASH_MODE_ON // 原生不直接支持torch模式
            }
            manager.setFlashMode(flashMode)
            callback(Result.success(Unit))
        } catch (e: Exception) {
            callback(Result.failure(MultiCameraFlutterError("SET_FLASH_MODE_FAILED", e.message ?: "Unknown error", null)))
        }
    }

    override fun startPreview(callback: (Result<Unit>) -> Unit) {
        try {
            val manager = getNativeCameraManager()
            manager.startPreview()
            callback(Result.success(Unit))
        } catch (e: Exception) {
            callback(Result.failure(MultiCameraFlutterError("START_PREVIEW_FAILED", e.message ?: "Unknown error", null)))
        }
    }

    override fun stopPreview(callback: (Result<Unit>) -> Unit) {
        try {
            val manager = getNativeCameraManager()
            manager.stopPreview()
            callback(Result.success(Unit))
        } catch (e: Exception) {
            callback(Result.failure(MultiCameraFlutterError("STOP_PREVIEW_FAILED", e.message ?: "Unknown error", null)))
        }
    }

    override fun dispose(callback: (Result<Unit>) -> Unit) {
        disposeCameraResources()
        callback(Result.success(Unit))
    }

    override fun isImplementationAvailable(
        implementationType: CameraImplementationType,
        callback: (Result<Boolean>) -> Unit
    ) {
        try {
            val isAvailable = when (implementationType) {
                CameraImplementationType.NATIVE -> true
                CameraImplementationType.FLUTTER_CAMERA -> {
                    // 检查是否有camera依赖
                    try {
                        Class.forName("io.flutter.plugins.camera.CameraPlugin")
                        true
                    } catch (e: ClassNotFoundException) {
                        false
                    }
                }
            }
            callback(Result.success(isAvailable))
        } catch (e: Exception) {
            callback(Result.failure(MultiCameraFlutterError("CHECK_IMPLEMENTATION_FAILED", e.message ?: "Unknown error", null)))
        }
    }

    override fun createCameraTexture(callback: (Result<CameraTexture>) -> Unit) {
        coroutineScope.launch {
            try {
                val manager = getNativeCameraManager()
                val previewUseCase = manager.getPreviewUseCase() ?: run {
                    callback(Result.failure(MultiCameraFlutterError("NOT_INITIALIZED", "Preview use case not available", null)))
                    return@launch
                }

                textureEntry?.release()

                val newTextureEntry = flutterPluginBinding?.textureRegistry?.createSurfaceTexture() ?: run {
                    callback(Result.failure(MultiCameraFlutterError("TEXTURE_ERROR", "Failed to create texture entry", null)))
                    return@launch
                }
                textureEntry = newTextureEntry

                val resolution = manager.getPreviewResolution()
                if (resolution == null) {
                    callback(Result.failure(MultiCameraFlutterError("TEXTURE_ERROR", "Failed to get camera resolution", null)))
                    return@launch
                }

                val surfaceTexture = newTextureEntry.surfaceTexture()
                surfaceTexture.setDefaultBufferSize(resolution.width, resolution.height)
                val surface = Surface(surfaceTexture)

                val mainExecutor = ContextCompat.getMainExecutor(context!!)
                previewUseCase.setSurfaceProvider(mainExecutor) { request ->
                    Log.d(TAG, "Surface requested for texture preview. Resolution: ${request.resolution}")
                    request.provideSurface(surface, mainExecutor) { surfaceResult: androidx.camera.core.SurfaceRequest.Result ->
                        Log.d(TAG, "Surface provider result: ${surfaceResult.resultCode}")
                        // Surface is released by the textureEntry.release()
                    }
                }
                
                val result = CameraTexture(
                    textureId = newTextureEntry.id(),
                    width = resolution.width.toDouble(),
                    height = resolution.height.toDouble()
                )
                callback(Result.success(result))

            } catch (e: Exception) {
                callback(Result.failure(MultiCameraFlutterError("TEXTURE_CREATION_FAILED", e.message, e.toString())))
            }
        }
    }

    override fun pauseSession(callback: (Result<Unit>) -> Unit) {
        try {
            val manager = getNativeCameraManager()
            manager.pauseSession()
            callback(Result.success(Unit))
        } catch (e: Exception) {
            callback(Result.failure(MultiCameraFlutterError("PAUSE_SESSION_FAILED", e.message ?: "Unknown error", null)))
        }
    }

    override fun resumeSession(callback: (Result<Unit>) -> Unit) {
        try {
            val manager = getNativeCameraManager()
            manager.resumeSession()
            callback(Result.success(Unit))
        } catch (e: Exception) {
            callback(Result.failure(MultiCameraFlutterError("RESUME_SESSION_FAILED", e.message ?: "Unknown error", null)))
        }
    }

    override fun isSessionPaused(callback: (Result<Boolean>) -> Unit) {
        try {
            val manager = getNativeCameraManager()
            val isPaused = manager.isSessionPaused()
            callback(Result.success(isPaused))
        } catch (e: Exception) {
            callback(Result.failure(MultiCameraFlutterError("CHECK_SESSION_STATE_FAILED", e.message ?: "Unknown error", null)))
        }
    }

    private fun disposeCameraResources() {
        Log.d(TAG, "Disposing camera resources")
        textureEntry?.release()
        textureEntry = null
        nativeCameraManager?.dispose()
        nativeCameraManager = null
    }
}
